package com.yihaodian.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;

import com.google.inject.Injector;
import com.yihaodian.api.common.Configs;
import com.yihaodian.cluster.ClusterModule;
import com.yihaodian.cluster.ClusterService;
import com.yihaodian.cluster.Node;
import com.yihaodian.cluster.discovery.DiscoveryModule;
import com.yihaodian.cluster.discovery.NodeDiscovery;
import com.yihaodian.common.ModulesBuilder;
import com.yihaodian.index.IndexModule;
import com.yihaodian.indices.IndicesClusterStateService;
import com.yihaodian.indices.IndicesModule;
import com.yihaodian.indices.IndicesService;
import com.yihaodian.search.SearchModule;
import com.yihaodian.search.broker.BrokerModule;

/**
 * start up service, register shard search to hedwig.
 * 
 * @author zhouhang
 * 
 */
public class NodeBootstrap {

	private static final Logger log = Logger.getLogger(NodeBootstrap.class);

	/**
	 * for test only
	 */
	static Map<Node, Injector> localNodes = new HashMap<Node, Injector>();

	Injector injector = null;

	String clusterId = null;

	Node node = null;

	Properties properties = new Properties();

	public NodeBootstrap(int port) {
		this.node = new Node(port);

		String clusterId = Configs.getClusterId();
		this.node.setClusterId(clusterId);
	}

	/**
	 * use Guice to create bean.
	 */
	void startupService() {
		String zkQuorums = Configs.getZkQuorums();
		String zkBaseDir = Configs.getZkRootPath();

		// instance
		ModulesBuilder builder = new ModulesBuilder();
		builder.add(new DiscoveryModule(zkQuorums, zkBaseDir, node));
		builder.add(new ClusterModule());
		builder.add(new IndexModule());
		builder.add(new IndicesModule());
		builder.add(new SearchModule());
		builder.add(new BrokerModule());

		injector = builder.createInjector();

		// startup
		injector.getInstance(ClusterService.class).startup();
		injector.getInstance(IndicesClusterStateService.class).startup();

		// last start
		injector.getInstance(NodeDiscovery.class).startup();
		

		localNodes.put(node, injector);
	}

	void stopService() {
		// stop first
		injector.getInstance(NodeDiscovery.class).shutdown();

		// stop
		injector.getInstance(IndicesService.class).shutdown();
	}

	/**
	 * start a target Node id, need Node port to register a service.
	 * 
	 * <pre>
	 * Node -> ClusterService -> LocalIndexService.startIndexEngine -> HedwigServiceProvider.register
	 * </pre>
	 * 
	 * @param nodeId
	 */
	public void startup() {
		startupService();
	}

	public void shutdown() {
		stopService();
	}

	public Injector getInjector() {
		return this.injector;
	}

	public Node getNode() {
		return node;
	}

	/**
	 * test interface.
	 * 
	 * @return
	 */
	public static List<Node> getLocalNodes() {
		return new ArrayList<Node>(localNodes.keySet());
	}
	
	public static Injector getInjector(Node node) {
		return localNodes.get(node);
	}
}
